/**
 * HTTP 请求封装
 * 基于 fetch API，提供统一的错误处理、拦截器、超时控制
 */

import logger from './logger'

// 请求配置接口
export interface RequestConfig extends RequestInit {
  url?: string // 请求 URL
  timeout?: number // 超时时间（毫秒）
  baseURL?: string // 基础 URL
  params?: Record<string, string | number | boolean> // URL 参数
  data?: unknown // 请求体数据
}

// 响应接口
export interface Response<T = unknown> {
  data: T
  status: number
  statusText: string
  headers: Headers
}

// 拦截器类型
type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>
type ResponseInterceptor = <T>(response: Response<T>) => Response<T> | Promise<Response<T>>
type ErrorInterceptor = (error: Error) => Promise<never>

class HttpClient {
  private baseURL = ''
  private timeout = 10000
  private requestInterceptors: RequestInterceptor[] = []
  private responseInterceptors: ResponseInterceptor[] = []
  private errorInterceptors: ErrorInterceptor[] = []

  constructor(config?: { baseURL?: string; timeout?: number }) {
    if (config?.baseURL) this.baseURL = config.baseURL
    if (config?.timeout) this.timeout = config.timeout
  }

  // 添加请求拦截器
  addRequestInterceptor(interceptor: RequestInterceptor): void {
    this.requestInterceptors.push(interceptor)
  }

  // 添加响应拦截器
  addResponseInterceptor(interceptor: ResponseInterceptor): void {
    this.responseInterceptors.push(interceptor)
  }

  // 添加错误拦截器
  addErrorInterceptor(interceptor: ErrorInterceptor): void {
    this.errorInterceptors.push(interceptor)
  }

  // 构建完整 URL
  private buildURL(url: string, params?: Record<string, string | number | boolean>): string {
    const fullURL = url.startsWith('http') ? url : `${this.baseURL}${url}`
    if (!params) return fullURL

    const searchParams = new URLSearchParams()
    Object.entries(params).forEach(([key, value]) => {
      searchParams.append(key, String(value))
    })
    return `${fullURL}?${searchParams.toString()}`
  }

  // 执行请求
  async request<T = unknown>(config: RequestConfig): Promise<Response<T>> {
    try {
      // 应用请求拦截器
      let finalConfig = { ...config }
      for (const interceptor of this.requestInterceptors) {
        finalConfig = await interceptor(finalConfig)
      }

      const { timeout = this.timeout, params, data, ...fetchOptions } = finalConfig
      const url = this.buildURL(finalConfig.url || '', params)

      // 设置请求体
      if (data) {
        fetchOptions.body = JSON.stringify(data)
        fetchOptions.headers = {
          'Content-Type': 'application/json',
          ...fetchOptions.headers
        }
      }

      // 超时控制
      const controller = new AbortController()
      const timeoutId = setTimeout(() => controller.abort(), timeout)
      fetchOptions.signal = controller.signal

      // 发起请求
      const fetchResponse = await fetch(url, fetchOptions)
      clearTimeout(timeoutId)

      // 解析响应
      const responseData = await fetchResponse.json()
      let response: Response<T> = {
        data: responseData,
        status: fetchResponse.status,
        statusText: fetchResponse.statusText,
        headers: fetchResponse.headers
      }

      // 应用响应拦截器
      for (const interceptor of this.responseInterceptors) {
        response = await interceptor(response)
      }

      return response
    } catch (error) {
      // 应用错误拦截器
      for (const interceptor of this.errorInterceptors) {
        await interceptor(error as Error)
      }
      throw error
    }
  }

  // 便捷方法
  get<T = unknown>(url: string, config?: RequestConfig): Promise<Response<T>> {
    return this.request<T>({ ...config, url, method: 'GET' })
  }

  post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<Response<T>> {
    return this.request<T>({ ...config, url, method: 'POST', data })
  }

  put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<Response<T>> {
    return this.request<T>({ ...config, url, method: 'PUT', data })
  }

  delete<T = unknown>(url: string, config?: RequestConfig): Promise<Response<T>> {
    return this.request<T>({ ...config, url, method: 'DELETE' })
  }
}

// 创建默认实例
const http = new HttpClient({
  baseURL: import.meta.env.VITE_API_BASE_URL || '',
  timeout: 10000
})

// 添加默认请求拦截器（添加 token）
http.addRequestInterceptor(async (config) => {
  const token = await window.api.getAppConfig('auth_token')
  if (token) {
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${token}`
    }
  }
  logger.debug('HTTP 请求', { url: config.url || '', method: config.method || 'GET' })
  return config
})

// 添加默认响应拦截器（统一处理业务错误）
http.addResponseInterceptor((response) => {
  if (response.status >= 400) {
    logger.error('HTTP 响应错误', { status: response.status, data: response.data })
    throw new Error(`请求失败: ${response.statusText}`)
  }
  return response
})

// 添加默认错误拦截器
http.addErrorInterceptor(async (error) => {
  if (error.name === 'AbortError') {
    logger.warn('请求超时')
    throw new Error('请求超时，请稍后重试')
  }
  logger.error('HTTP 请求失败', { error: error.message })
  throw error
})

export default http
